﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UtilZ.Dotnet.Ex.ZLog;

namespace UtilZ.Dotnet.Ex.Communication.Net.Ftp
{
    /// <summary>
    /// 从指定点重新开始传输
    /// Restart transfer from the specified point.
    /// </summary>
    internal class FtpRESTCommand : FtpCommandAbs
    {
        /***********************************************************************************************************
        * [REST]（Restart，重新启动）命令
        * 说明：标识出文件内的数据点，将从这个点开始继续传送文件。
        * 
        * 用法：REST<Marker><CRLF>
        * 参数：Marker代表文件传送将要由此重新启动的服务器标记。
        * 例子：
        * SendData "REST 244" + “/r/n
        * 
        * 注释：REST不会引起文件传送，而只是跳到文件中指定的数据检验点上。RSET后紧跟着适当的FTP服务命令，该命令才会引起文件的继续传送。
        * 返回值如下（粗体表示成功）：
        * 无响应即表示成功。
        * 350  请求的文件操作在等待更进一步的信息。
        * 421  服务不可用，关闭控制连接。
        * 
        * 如果某项服务获知自己即将关闭，会向所有命令做出这个应答。
        * 500  语法错误，无法识别命令。这其中包括命令行过长之类的错误。
        * 501  参数或变元中有语法错误。
        * 502  命令还没有被实现。
        * 530  无法登录。
        * 
        ************************************************************************************************************/


        public FtpRESTCommand()
            : base()
        {

        }

        protected override string[] GetNames()
        {
            return new string[] { FtpCommands.REST };
        }

        protected override IFtpResponse PrimitiveExcute(FtpSession session, string command, string commandLine)
        {
            //未抓包验证
            //Request: REST 187392
            //Response: 350 Restarting at 187392.Send STOTE or RETRIEVE to initiate transfer.


            try
            {
                if (!session.AllowWrite())
                {
                    return new FtpCodeResponse(FtpStatusCodes.Code550, "Access is denied. ");
                }

                string posStr = commandLine;
                if (string.IsNullOrEmpty(posStr))
                {
                    return new FtpCodeResponse(FtpStatusCodes.Code500, "The parameter is required to specify the file start location");
                }

                long pos;
                if (long.TryParse(posStr.Trim(), out pos))
                {
                    session.RestPosition = pos;
                    return new FtpCodeResponse(FtpStatusCodes.Code350, $"Restarting at {pos}.Send STOTE or RETR to initiate transfer.");
                }
                else
                {
                    return new FtpCodeResponse(FtpStatusCodes.Code500, $"File start location {pos} value is invalid.");
                }
            }
            catch (Exception ex)
            {
                return new FtpCodeResponse(FtpStatusCodes.Code451, ex.Message);
            }
        }
    }

}
